import pygame, sys, json, os, random

from constants import *

from sprites import Player, TileCursor, GroundTile, ObstacleTile
from sprite_groups import CameraGroup

# Initialize Pygame
pygame.init()

with open('./assets/map.json') as f:
    tile_map = json.load(f)

imgs = {}
with open('./assets/tiles.json') as f:
    tiles = json.load(f)

for tile_ident in tiles:
    tile = tiles[tile_ident]
    if os.path.exists(tile['image']['path']):
        tile['image']['surface'] = pygame.image.load(tile['image']['path'])
    else:
        print(f'WARNING: Image for tile {tile_ident} is missing')
        tile['image']['surface'] = pygame.surface.Surface((64, 64))
        tile['image']['surface'].fill((random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255)))

# Create the game window
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("FamingGame-Pygame")

# Create sprite groups
all_sprites = pygame.sprite.Group()
obstacles = pygame.sprite.Group()
tile_sprites = pygame.sprite.Group()

tile_cursor = TileCursor(0, 0)

# Create player and obstacles
player = Player()
all_sprites.add(player, tile_cursor)

camera_group = CameraGroup(tile_cursor)
camera_group.add(player)

# Create the game clock
clock = pygame.time.Clock()

tile_map_sprites = {}
def add_sprite_to_map(sprite, layer, x, y):
    if not layer in tile_map_sprites:
        tile_map_sprites[layer] = {}
    if not y in tile_map_sprites[layer]:
        tile_map_sprites[layer][y] = {}
    if not x in tile_map_sprites[layer][y]:
        tile_map_sprites[layer][y][x] = sprite

def get_sprites_at_coordinate(x, y, layer=None):
    out = []
    if layer == None:
        for map_layer in tile_map_sprites:
            if y in tile_map_sprites[map_layer]:
                if x in tile_map_sprites[map_layer][y]:
                    out.append(tile_map_sprites[map_layer][y][x])
    else:
        if layer in tile_map_sprites:
            if y in tile_map_sprites[layer]:
                if x in tile_map_sprites[layer][y]:
                    out.append(tile_map_sprites[layer][y][x])
    return out

def create_tile_sprite(tile: str, layer, tile_x, tile_y):
    if tiles[tile]['type'].lower() == 'ground':
        new_sprite = GroundTile(tiles, tile_x * 64, tile_y * 64, tile)
        tile_sprites.add(new_sprite)
        camera_group.add_tile(new_sprite)
        add_sprite_to_map(new_sprite, layer, x, y)
        all_sprites.add(new_sprite)
        return new_sprite
    elif tiles[tile]['type'].lower() == 'obstacle':
        new_sprite = ObstacleTile(tiles, tile_x * 64, tile_y * 64, tile)
        obstacles.add(new_sprite)
        camera_group.add(new_sprite)
        add_sprite_to_map(new_sprite, layer, tile_x, tile_y)
        return new_sprite

for layer, map in enumerate(tile_map):
    for y, column in enumerate(map):
        for x, tile in enumerate(column):
            if tile == None:
                continue
            elif tile in tiles:
                create_tile_sprite(tile, layer, x, y)

# Game loop
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONUP:
            sprite_coordinate_under_mouse = camera_group.get_sprite_coordinate_under_cursor()
            cursor_x, cursor_y = sprite_coordinate_under_mouse
            sprites_under_cursor = [i.ident for i in get_sprites_at_coordinate(cursor_x, cursor_y)]
            if event.button == 1: # Left Click
                if len(sprites_under_cursor) == 1:
                    sprite_under_cursor = sprites_under_cursor[0]
                    if sprite_under_cursor == 'grass':
                        sprite = get_sprites_at_coordinate(cursor_x, cursor_y, 0)[0]
                        sprite.change_type(tiles, 'dirt')
                    elif sprite_under_cursor == 'dirt':
                        sprite = get_sprites_at_coordinate(cursor_x, cursor_y, 0)[0]
                        sprite.change_type(tiles, 'tilled_dirt')
                    elif sprite_under_cursor == 'tilled_dirt':
                        sprite = get_sprites_at_coordinate(cursor_x, cursor_y, 0)[0]
                        sprite.change_type(tiles, 'dirt')
            elif event.button == 2: # Middle Click
                print(sprite_coordinate_under_mouse, [i.ident for i in get_sprites_at_coordinate(cursor_x, cursor_y)])
            elif event.button == 3: # Right Click
                if len(sprites_under_cursor) > 0:
                    if sprites_under_cursor[0] == 'tilled_dirt':
                        if len(sprites_under_cursor) > 1:
                            sprite = get_sprites_at_coordinate(cursor_x, cursor_y, 1)[0]
                            sprite.change_type(tiles, 'wheat_0')    
                        else:
                            create_tile_sprite('wheat_0', 1, cursor_x, cursor_y)
            elif event.button == 4: # Scroll Up
                pass
            elif event.button == 5: # Scroll Down
                pass

    # Update
    all_sprites.update(obstacles, tile_sprites)

    # Render
    screen.fill(BG_COLOR)
    camera_group.camera_draw(screen, player)

    # Update the display
    pygame.display.flip()

    # Cap the frame rate
    clock.tick(FPS)

# Quit the game
pygame.quit()
sys.exit()
